<?php
/*
 +----------------------------------------------------------------------
 | TEMMOKUMVC [ NO BEST, ONLY BETTER ]
 +----------------------------------------------------------------------
 | Copyright (c) 2018~2019 https://www.temmoku.cn All rights reserved.
 +----------------------------------------------------------------------
 | Author: 张宗强 Email:webmaster@temmoku.cn QQ:158726877 516669373 TEL:17895221001 微信:temmokumvc
 +---------------------------------------------------------------------- 
*/
namespace temmoku\lib;
class template{
	
	private  $_dir; //获取当前目录绝对地址
	private  $content; //当前模板的主内容。实时更新的
	private  $_star_tag='{{'; //开始标记
	private  $_end_tag='}}'; //结束标记
	private static  $vendor=[];//执行的第三方库
	public function display($dir){
		$_basename= basename($dir);
		$path=pathinfo($dir);
		$_path=explode('/'.DEVICE,$path['dirname'],'2');
		$end_path=DEVICE.$_path['1'];
		$_dir= defined('M_MODULE')==false ? (defined('P_MODULE')==true ? P_MODULE : "") : M_MODULE;
		if($_dir){
			$_dir="/".$_dir."/";
		}

		//添加MD5防止破解到模板路径
		$tmp_file=RUNTIME_PATH.'tmp/'.MODULE.$_dir.'/template_cache/'.strtolower($end_path).'/'.$path['filename'].'_'.MD5(C('MD5')).'.txt';
		
		if(C('iswrite_Template')=='0' && is_file($tmp_file)){
			return $tmp_file;
		}
		$this->_dir=dirname($dir);
		
		//先将模板内容读取出来
		$this->content=fils_content($dir);
		
		//替换反写刚
		$this->content=str_ireplace ( '\\\\' , '\\' , $this->content );
		$this->content=str_ireplace ( '\\' , '\\\\' , $this->content );
		
		//然后解析 include .返回的是内容
		$this->_include_();
		
		//执行第三方方法
		$this->vendor_exec();
		
		//解析变量
		$this->_variable_();
		//循环语句
		$this->_foreach_();
		//判断语句
		$this->_if();
		//explode函数
		$this->_explode();
		//php标签
		$this->_php();
		
		$this->_function();

		//SQL 标签
		$this->_sql();
		
		write_file($tmp_file,$this->content);
		$this->content='';
		return	$tmp_file;
	}
	private function vendor_exec(){
		if(self::$vendor){
			foreach(self::$vendor as $class=>$menthod){
				try{
					if(is_array($menthod)){
                    	foreach($menthod as $_menthod){
                          	$this->content=(new $class)->$_menthod($this->content);
                        }
                    }else{
                    	$this->content=(new $class)->$menthod($this->content);
                    }
				}catch(\Exception $e){
					echo "执行:{$class}类,{$menthod}方法出错\n";
					continue ;
				}
			}
		}
	}
	
	/*	$class 需要执行的命名空间全名
		$menthod 执行的方法
	*/
	public function set($class,$menthod){
		self::$vendor = array_merge(self::$vendor,[$class=>$menthod]);
	}
	
	private function _sql(){
		if(preg_match_all('#<sql(.*?)>#is', $this->content, $matches)){
			foreach($matches[0] AS $key=>$text){
				$data=$this->array_bind($text);
				list($px,$table)=explode(".",$data['from']);
				if($table) { $from="$px.\"$table\"" ;}else{$from="\"$data[from]\"";} 
				$data['out'] ? $out=$data['out'] :$out='sql';
				$data['select'] ? $select=$data['select'] :$select='*';
				$data['where'] ? $where=$data['where'] :$where='1';
				$groupby=$join=$by=$start_limit=$limit='';
				if($data['order'] && $data['by']){
					$order=[];
					foreach(explode(',',$data['order']) AS $__order){
						$order[] ="'$__order'";
					}
					$order=implode(',',$order);
					$_by=strtoupper($data['by']);
					if($_by=='DESC' || !$_by){
						$by="orderByDESC([$order])->";
					}else{
						$by="orderByASC([$order])->";
					}
				}
				//过滤重复
				if($data['groupby']){
					$groupby=[];
					foreach(explode(',',$data['groupby']) AS $__groupby){
						$groupby[] ="'$__groupby'";
					}
					$groupby=implode(',',$groupby);
					$groupby="groupBy([$groupby])->";
				}
				//连表查询
				if($data['join']){
					foreach($data['join'] AS $value){
						list($a,$b)=explode(",",$value);
						list($_px,$_table)=explode(".",$a);
						if($_table) { $_join="$_px.\"$_table\"" ;}else{$_join="\"$a\"";} 
						$join .="innerJoin($_join,\"$b\")->";
					}
				}
				if($data['single']){
					$q="row()";
				}else{
					intval($data['start_limit']) ? $start_limit=$data['start_limit'] :$start_limit='0';
					intval($data['limit']) ? $limit=$data['limit'] :$limit='10';
					$start_limit ="start_limit($start_limit)->";
					$limit 		 ="limit($limit)->";
					$q="query()";
				}
				$out="<?php unset($$out);$$out=\\\\temmoku\\\\db::from($from)->select(\"$select\")->{$join}where(\"$where\")->{$by}{$groupby}{$start_limit}{$limit}{$q} ;?>";
				
				$this->content=str_replace($matches[0][$key],$out,$this->content);
			}
		}
	}
	
	private function _php(){
		preg_match_all('/<php>/is', $this->content, $start);
		preg_match_all('/<\/php>/is', $this->content, $end);
		if(count($start[0])==count($end[0])){
			$this->content=str_ireplace("<php>","<?php  ",$this->content);
			$this->content=str_ireplace("</php>"," ?>",$this->content);
		}
	}
	
	private function _explode(){
		if(preg_match_all('#<explode(.*?)>#is', $this->content, $matches)){
			foreach($matches[1] AS $key=>$text){
				$data=$this->array_bind($text);
				if($data['out']=='list'){
					$_list=explode(',',$data['assign']);
					foreach($_list AS $value){
						$assign []= '$'.$value;
					}
					$out='<?php list('.implode(',',$assign).')=explode("'.$data['separator'].'",$'.$data['value'].') ?>';
				}else{
					$out='<?php $'.$data['out'].'=explode("'.$data['separator'].'",$'.$data['value'].') ?>';
				}
				$this->content=str_replace($matches[0][$key],$out,$this->content);
			}
		}
	}
	
	//匹配include的方法
	private function _include_(){
		$_Include = "/{$this->_star_tag}.*include.*file=(.*?){$this->_end_tag}/";
		if(preg_match_all($_Include,$this->content,$matches)){
			
			foreach($matches[1] AS $k=>$v){
				if(preg_match('/^Main_View/i',$v,$m)){
					eval( "\$include_dir =  $v ;" );
				}else{
					//防止是全地址要进行判断下
					if(is_file($v)){
						$include_dir=$v;
					}else{
						$include_dir=$this->_dir.'/'.$v;
					}
				}
				if(strpos ($include_dir,"::parsing")){
					$include_dir=str_replace("\\","\\\\",$include_dir);
					$include_content="<?php $include_dir ?>";
				}else{
					$include_content=fils_content($include_dir);
				}
				$this->content=str_replace($matches[0][$k],$include_content,$this->content);
				if(preg_match_all($_Include,$include_content)){
					$this->_include_();
				}
			}
		}
	}
	
	private function _foreach_(){
		preg_match_all('/<foreach(.*?)>/is', $this->content, $start);
		preg_match_all('/<\/foreach>/is', $this->content, $end);
		if(count($start[0]) != count($end[0])){
			return;
		}
		if($start){
			foreach($start[1] AS $key=>$text){
				$data=$this->array_bind($text);
				isset($data['value']) ? $value=$data['value'] :$value='row';
				isset($data['key']) ? $_key=$data['key'] :$_key='key';
				if($data['f']){
					$out= "<?php foreach((array)$data[array] AS \$$_key=>\$$value){ ?>";
				}else{
					$out= "<?php foreach((array)\$$data[array] AS \$$_key=>\$$value){ ?>";
				}
				
				$this->content=str_replace($start[0][$key],$out,$this->content);
			}
		}
		if($end){
			foreach($end[0] AS $key=>$text){
				$this->content=str_ireplace("</foreach>","<?php } ?>",$this->content);
			}
		}
	}
	

	private function _if(){	
		preg_match_all('/<if\s(.*?)>/is', $this->content, $start);
		preg_match_all('/<elseif(.*?)>/is', $this->content, $elseif);
		preg_match_all('/<else>/is', $this->content, $else);
		preg_match_all('/<\/if>/is', $this->content, $end);
		if(count($start[0]) != count($end[0])){
			return;
		}
		if($start){
			foreach($start[1] AS $key=>$text){
				$data=$this->array_bind(" ".$text);
				$out= "<?php if($data[condition]){ ?>";
				$this->content=str_replace($start[0][$key],$out,$this->content);
			}
		}
		if($elseif){
			unset($_matches);
			foreach($elseif[1] AS $key=>$text){
				$data=$this->array_bind($text);
				$out= "<?php }elseif($data[condition]){ ?>";
				$this->content=str_replace($elseif[0][$key],$out,$this->content);
			}
		}
		if($else){
			$this->content=str_replace("<else>","<?php }else{ ?>",$this->content);
		}
		if($end){
			$this->content=str_replace("</if>","<?php } ?>",$this->content);
		}
	}
	
	
	//数组合并
	private function array_bind($text){
		$regex  = '/\s+(?>([\w-]+)\s*)=(?>\s*)([\"\'])((?:(?!\\2).)*)\\2/is';
		preg_match_all($regex, $text, $_matches);
		$data=[];
		foreach($_matches[1] AS $_key=>$key){
			$key=strtolower($key);
			$value=str_replace(" egt "," >= ",$_matches[3][$_key]);
			$value=str_replace(" elt "," <= ",$value);
			$value=str_replace(" gt "," > ",$value);
			$value=str_replace(" lt "," < ",$value);
			if($key=='join'){
				$data[$key][]=$value;
			}else{
				$data[$key]=$value;
			}
		}
		return $data;
	}
	
	
	//变量
	private function _variable_(){
		$regular = "/{$this->_star_tag}[\s]*+\\$(.*?)[\s]*+{$this->_end_tag}/";
		if(preg_match_all($regular,$this->content,$matches)){
			//print_r($matches);
			foreach($matches['1'] AS $key=>$v){
				//匹配任何空白字符
				$v=preg_replace ( '/([\s])*/' ,'',  $v );
				if(strpos($v,'.')){
					$_v=explode('.',$v);
					$name=$_v[0];
					unset($_v[0]);
					$___v=[];
					foreach($_v AS $__v){
						$___v[]='[\''.$__v.'\']';
					}
					$return = '$'.$name.implode('',$___v);
				}else{
					$return	= '$'.$v;
				}
				$this->content=str_replace($matches['0'][$key],'<?php echo '.$return .' ?>',$this->content); 
			}
		}
	}
	private function _function(){
		$regular = "/{$this->_star_tag}[\s]*+(.*?)[\s]*+{$this->_end_tag}/";
		if(preg_match_all($regular,$this->content,$matches)){
			foreach($matches[1] AS $key=>$value){
				if(stripos($value,'hook_listen')===0){
					$this->content=str_replace($matches[0][$key],'<?php '.$value .' ?>',$this->content); 
				}else{
					$this->content=str_replace($matches[0][$key],'<?php echo '.$value .' ?>',$this->content); 
				}
			}
		}
		/* $this->content = preg_replace($regular, "<?php echo \\1; ?>", $this->content ); */
	}
}
?>
